using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
using System.Management;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Threading;

namespace ERPStudio
{
    public class Autorizare
    {
        
        /// <summary>
        /// deplasamentul in fisierul din cu autorizarile pentru module
        /// </summary>
        public long DeplasamentFisier = -1;

        [DllImport("kernel32.dll")]
        private static extern Int32 GetVolumeInformation(string PathName, StringBuilder VolumeNameBuffer, UInt32 VolumeNameSize, ref UInt32 VolumeSerialNumber, ref UInt32 MaximumComponentLength, ref UInt32 FileSystemFlags, StringBuilder FileSystemNameBuffer, UInt32 FileSystemNameSize);
        //public List<ModuleStruct> lstModule = new List<ModuleStruct>();
        private UInt32 m_NumarZileFunctionare = 0;
        private Int32[]  tabhash_client={3,13,7,2,18,17,5,9,10,15,4,19,11,16,1,6,8,12,14,0};
        private Int32[]  tabhash_transmis={7,3,1,11,19,4,15,16,0,5,17,8,14,13,9,6,18,12,2,10};
        private Int32[]  tabhash_temp={7,3,1,11,4,15,0,5,8,14,13,9,6,12,2,10};

        
        
        public bool eLiteraMare(Byte x)
        {
            return (x>=65) && (x<=90);
        }
        public bool eLiteraMica(Byte x)
        {
            return (x>=97) && (x<=122);
        }
        public bool eCifra(Byte x)
        {
            return(x>=48) && (x<=57);
        }
        public Int32 min(Int32 x, Int32 y)
        {
            if (x < y)
                return x;
            return y;
        }
        public Autorizare()
        { 
        
        }
        public void MyTrace(String val)
        {
            Trace.WriteLine("[" + DateTime.Now.ToString() + "]" + val);
        }
        
        public bool SuntEgaleCheile(String s1,String s2)
        {
            Int16 idmod1=0,idmod2=0;
	        String ret1 =  _GetHDId(s1,tabhash_client,ref idmod1);
	        String ret2 =  _GetHDId(s2,tabhash_transmis,ref idmod2);
	        if(ret1 == String.Empty || ret2 == String.Empty || 
                ret1 == null || ret2 == null)
		        return false;
	        return ret1==ret2 && idmod1==idmod2;
        }
        public String _GetHDIdCl(String cheie,ref Int16 idMod)
        {
            return _GetHDId(cheie, tabhash_client,ref idMod);
        }
        public String _GetHDIdTr(String cheie,ref Int16 idMod)
        {
            return _GetHDId(cheie, tabhash_transmis,ref idMod);
        }
        private String _GetHDId(String cheie,Int32[] tabhash,ref Int16 modulID)
        {
            modulID = 0;
	        if(cheie.Length<20)
		        return String.Empty;
	        char[] strCheie= new char[20],sn = new char[20];
            for (Int16 ii = 0; ii < 20; ii++)
            {
                strCheie[ii] = 'A';
                sn[ii] = ' ';
            }
	        for(Int32 i=0;i<20;i++)
		        sn[i] = cheie[tabhash[i]];

	        int lgCheie = sn[0]-65;
	        //pe prima pozitie pune lungimea chei
            if (lgCheie < 5)
            {
                MyTrace("lgCheie < 5");
                return String.Empty;
            }

	        Int32 c;
	        Int32 maxit = min(lgCheie,19);
            //se analizeaza toata cheia pentru ca la sfarsit e id-ul
            //modulului
	        for(Int16 i=0;i<maxit;i++)
            {
		        if(eLiteraMare((Byte)sn[i+1])){
			        c = (sn[i+1] - 65);
			        c = 24 - c;
			        strCheie[i] = (char)(65 + c);
		        }
                if (eCifra((Byte)sn[i + 1]))
                {
			        c = (sn[i+1] - 48);
			        c = 9 - c;
			        strCheie[i] = (char)(48 + c);
		        }
	        }
            StringBuilder retB= new StringBuilder(),retID = new StringBuilder();
            for (UInt16 index = 0; index < lgCheie-2; index++)
                retB.Append(strCheie[index]);
            retID.Append(strCheie[lgCheie - 2]);
            retID.Append(strCheie[lgCheie - 1]);
            modulID = Convert.ToInt16(retID.ToString());
            return retB.ToString();	
        }
        private String _GetZilePrelungire(String cheie,int[] tabhash)
        {
	        if(cheie.Length<16)
		        return String.Empty;
	        Byte[] strCheie = new Byte[20],sn = new Byte[20];
            UInt16 i = 0;
	        for(i=0;i<16;i++)
		        sn[i] = (Byte)cheie[tabhash[i]];

	        int lgCheie = sn[0]-65;
	        //pe prima pozitie pune lungimea chei
	        if(lgCheie==0)
		        return String.Empty;

	        int c;
	        int maxit = min(lgCheie,16);
            StringBuilder retStr = new StringBuilder();
	        for(i=0;i<maxit;i++)
            {
		        if(eLiteraMare(sn[i+1]))
                {
			        c = (sn[i+1] - 65);
			        c = 24 - c;
                    retStr.Append((Char)(65 + c));
		        }
		        if(eCifra(sn[i+1]))
                {
			        c = (sn[i+1] - 48);
			        c = 9 - c;
			        retStr.Append((Char)(48 + c));
		        }
	        }
            return retStr.ToString();	
        }
        public String GetZilePrelungire(String cheie)
        {
            return _GetZilePrelungire(cheie, tabhash_temp);
        }

        /// <summary>
        /// schimba starile si nr. de zile din fisierul de autorizare
        /// </summary>
        /// <param name="indexCB"></param>
        /// <param name="cheie"></param>
        /// <returns></returns>
        public bool SaveAuth(int indexCB, String cheie, List<eInfoModule> lstModule)
        {

            String strPath = System.Environment.GetCommandLineArgs()[0];
            strPath = strPath.Replace(".vshost", null);
            strPath = strPath.Replace(".exe", ".din");

            FileStream fh1=null;
            try
            {
                fh1 = File.Open(strPath, FileMode.Open,FileAccess.ReadWrite);
                if (DeplasamentFisier  == 0)
                { 
                   //eroare citire din
                    MessageBox.Show("Eorare stabilire deplasament cheie in din!", "Eroare");
                    return false;
                }
                // se pozitioneaza unde incep informatiile despre module
                fh1.Seek(DeplasamentFisier, SeekOrigin.Begin);
           }
           catch(Exception ex)
           {
               fh1.Close();
               throw(new Exception("Eorare deschidere fisier!",ex));
           }
            
	       //citire cheie autorizare

	        if(cheie.Length==16)
            {
                foreach (eInfoModule ms in lstModule)
                {
                    if (ms.IDLista == indexCB)
                    {
                        ms.NrZileFunctionare = Convert.ToInt16(GetZilePrelungire(cheie));
                        ms.StareModul = 0;
                        break;
                    }
                }
            }
	        else
            {
                foreach (eInfoModule ms in lstModule)
                {
                    if (ms.IDLista == indexCB)
                    {
                        ms.StareModul  = 2; //stabilizat
                        break;
                    }
                }
	        }
           

            ushort lgSN2 = 0;
            Byte[] SerialNumber = GetVolumeSerialNumber(out lgSN2);
            ///salveaza numarul de module instalate
            ///
            int nrModuleInstalate = 0;
            foreach (eInfoModule md in lstModule)
                if (md.mModule != null)
                    nrModuleInstalate++;

            Byte[] strlgSN = new Byte[4];
            strlgSN[0] = (Byte)(nrModuleInstalate % 16);
            strlgSN[1] = (Byte)(nrModuleInstalate / 16);
            strlgSN[2] = 0;
            strlgSN[3] = 0;
            Boolean done = true;
            done &= SalvareBloc(strlgSN, fh1, 4);
            foreach (eInfoModule ms in lstModule)
            {
                SalveazaBlocModul(ms, SerialNumber, lgSN2, fh1);
            }
            fh1.Flush();
            fh1.Close();  
            return true;

        }

        /*public Boolean IsAuthorizedOneModule()
        {
            Boolean ret = false;
            foreach (ModuleStruct ms in lstModule)
            {
                if (ms.StareModul == 2)
                {
                    ret = true;
                    break;
                }
            }
            return ret;

        }*/

        /// <summary>
        ///  returneaza seria volumului
        /// </summary>
        /// <param name="lgSN">returneaza lungimea cheii</param>
        /// <returns></returns>
        /// 
        public Byte[] GetVolumeSerialNumber(out UInt16 lgSN)
        {
            lgSN = 0;
            Byte[] Ret = new Byte[20];

            uint serNum = 0;
            uint maxCompLen = 0;
            StringBuilder VolLabel = new StringBuilder(256); // Label
            UInt32 VolFlags = new UInt32();
            StringBuilder FSName = new StringBuilder(256); // File System Name
            String strDriveLetter = "C:\\"; // fix up the passed-in drive letter for the API call
            long Retu = GetVolumeInformation(strDriveLetter, VolLabel, (UInt32)VolLabel.Capacity, ref serNum, ref maxCompLen, ref VolFlags, FSName, (UInt32)FSName.Capacity);
            String Ret1 = Convert.ToString(serNum);
            foreach (Char c in Ret1)
            {
                Ret[lgSN++] = (Byte)c;
            }
            return Ret;
        }
        public String GetVolumeSerialNumber()
        {
            uint serNum = 0;
            uint maxCompLen = 0;
            StringBuilder VolLabel = new StringBuilder(256); // Label
            UInt32 VolFlags = new UInt32();
            StringBuilder FSName = new StringBuilder(256); // File System Name
            String strDriveLetter = "C:\\"; // fix up the passed-in drive letter for the API call
            long Retu = GetVolumeInformation(strDriveLetter, VolLabel, (UInt32)VolLabel.Capacity, ref serNum, ref maxCompLen, ref VolFlags, FSName, (UInt32)FSName.Capacity);
            return Convert.ToString(serNum);
        }


        public bool CreateDin(String caleDest,List<eInfoModule> lstModule)
        {
            // Parametrii:
            //	caledest poate sa fie fisierul sau calea destinatie
            //  numele serverului (sau adresa IP)

            String strAppNameParent = System.Environment.GetCommandLineArgs()[0];
            bool done = false;

            String strPath, strCd = caleDest;
            strCd.Trim();
            strCd.Replace("\"", null);
            strCd = strCd.ToLower();

            if (!strCd.Contains(".din"))
            {
                if (strCd.Substring(strCd.Length - 1, 1) != "\\")
                    strCd += "\\";
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("{0}{1}.din", strCd, strAppNameParent);
                strPath = sb.ToString();
            }
            else
                strPath = strCd;
            Stream writer = File.Create(strPath);
            try
            {
                //salvare data
                Byte[] chestiuni = new Byte[6];
                DateTime st = DateTime.Today;
             
                //salveaza data dar fix de-ampulea
                chestiuni[0] = (Byte)(st.Day % 16);
                chestiuni[1] = (Byte)(st.Month / 16);
                chestiuni[2] = (Byte)(st.Month % 16);
                chestiuni[3] = (Byte)(st.Day / 16);
                chestiuni[4] = (Byte)(st.Year % 16);
                chestiuni[5] = (Byte)(st.Year / 16);

                done &= SalvareBloc(chestiuni, writer, 6);
                done &= SalvareBloc(new Byte[17], writer, 17);
                done &= SalvareBloc(new Byte[34], writer, 34);

                UInt16 lgSN; //lungimea numarului serial
                Byte[] SerialNumber = GetVolumeSerialNumber(out lgSN), strlgSN= new Byte[4];
                if (lgSN > 17)
                    MessageBox.Show("Probleme grave de autorizare!!");
                strlgSN[0] =  (Byte)(lgSN%16);
                strlgSN[1] =  (Byte)(lgSN/16);
                strlgSN[2] =  0;    
                strlgSN[3] =  0;    
 
                done &= SalvareBloc(strlgSN, writer, 4);
                done &= SalvareBloc(SerialNumber, writer, (UInt32)SerialNumber.Length);

                done &= SalvareBloc(new Byte[24], writer, 24);
                done &= SalvareBloc(new Byte[4], writer, 4);
                //autorizarea sub forma xxxx-xxxx-xxxx-xxxx-xxxx
                //_CalcCheieSerial(theApp.m_strSerialNo,tabhash_client);
                done &= SalvareBloc(CalcCheieSerial(SerialNumber, tabhash_client), writer, 20);
                done &= SalvareBloc(new Byte[3], writer, 3);
                done &= SalvareBloc(new Byte[11], writer, 11);
                //autorizarea
                done &= SalvareBloc(new Byte[20], writer, 20);
                done &= SalvareBloc(new Byte[17], writer, 17);
                //numarul de zile de test
                Byte[] zile = { 70%16, 70/16, 0, 0}; 
                done &= SalvareBloc(zile , writer, 4);

                Trace.Assert(lstModule.Count!=0,"Nu exista nici un modul instalat");

                done &= SalvareBloc(new Byte[22], writer, 22);
                done &= SalvareBloc(new Byte[48], writer, 48);


                int nrModuleInstalate = 0;
                foreach (eInfoModule md in lstModule)
                    if (md.mModule != null)
                        nrModuleInstalate++;

                ///salveaza numarul de module instalate
                strlgSN[0] = (Byte)(nrModuleInstalate % 16);
                strlgSN[1] = (Byte)(nrModuleInstalate / 16);
                strlgSN[2] = 0;
                strlgSN[3] = 0;

                done &= SalvareBloc(strlgSN, writer, 4);
                foreach(eInfoModule ms in lstModule)
                {
                    ms.NrZileFunctionare = 170;
                    ms.DataInstalare = DateTime.Now;
                    ms.StareModul = 0; ///demonstrativ
                    SalveazaBlocModul(ms, SerialNumber, lgSN,writer );              
                }

                done = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Eroare salvare: " + ex.Message);
            }
            finally
            {
                writer.Close();
            }
            return done;
        }


        public Boolean SalveazaBlocModul(eInfoModule ms, Byte[] SerialNumber, int lgSN, Stream writer)
        {
            Boolean done = true;
            if (ms.mModule == null)
                return done;
            done &= SalvareBloc(new Byte[24], writer, 24);
            done &= SalvareBloc(new Byte[40], writer, 40);
            //id-ul modulului va avea maxim 2 cifre si se va afla

            String moduleID = String.Empty;
            if(ms.idModul!=null)
                moduleID = ms.idModul.ToString();
            // la sfarsitul numarului serial
            SerialNumber[lgSN] = (Byte)moduleID[0];
            SerialNumber[lgSN + 1] = (Byte)moduleID[1];
            done &= SalvareBloc(CalcCheieSerial(SerialNumber, tabhash_client), writer, 20);

            ///salveaza data de la care incepe sa lucreze cu modului!
            Byte[] chestiuni = new Byte[6];
            chestiuni[0] = (Byte)(ms.DataInstalare.Day % 16);
            chestiuni[1] = (Byte)(ms.DataInstalare.Month / 16);
            chestiuni[2] = (Byte)(ms.DataInstalare.Month % 16);
            chestiuni[3] = (Byte)(ms.DataInstalare.Day / 16);
            chestiuni[4] = (Byte)(ms.DataInstalare.Year % 16);
            chestiuni[5] = (Byte)(ms.DataInstalare.Year / 16);
            done &= SalvareBloc(chestiuni, writer, 6);

            Byte[] buffer = new Byte[4];
            ///starea modulului
            buffer[0] = (Byte)(ms.StareModul % 16);
            buffer[1] = (Byte)(ms.StareModul / 16);
            buffer[2] = 0;
            buffer[3] = 0;
            done &= SalvareBloc(buffer, writer, 4); //stare modul

            done &= SalvareBloc(new Byte[31], writer, 31);
            done &= SalvareBloc(new Byte[19], writer, 19);
            //autorizarea
            done &= SalvareBloc(new Byte[27], writer, 27);
            done &= SalvareBloc(new Byte[97], writer, 97);
            //numarul de zile de test
            buffer[0] = (byte)(ms.NrZileFunctionare % 16);
            buffer[1] = (byte)(ms.NrZileFunctionare / 16);
            buffer[2] = 0;
            buffer[3] = 0;
            done &= SalvareBloc(buffer, writer, 4);
            return done;
        }


        public bool SalvareBloc(Byte[] sir,Stream fh1,UInt32 lungime)
        {
	        //salveaza un bloc cu anumite informatii
	        Byte[] buf_w = new Byte[1024];
            Random fRand = new Random((int)DateTime.Now.Ticks);
            
	        int LungimeBloc = 0;
            for (int i = 0; i < DateTime.Now.Millisecond; i++)
                fRand.Next();
	        while(LungimeBloc<(146 + lungime*4))
		        LungimeBloc = fRand.Next()%1024;

            //obtine lungimea blocului ca si un numar aleator

	        bool exista;
	        //pe primi 2 byte este lungimea blocului
	        buf_w[0] = (Byte)Convert.ToChar(LungimeBloc%16);
	        buf_w[1] = (Byte)Convert.ToChar(LungimeBloc / 16);

            UInt32 j = 0;
	        //creaza o tabela de hassing pe lungimea sirului 
	        for(j=2;j<lungime+2;j++)
            {
		        do
                {
			        exista = false;
			        //genereaza o pozitie din interiorul blocului
			        buf_w[j] = (Byte) (fRand.Next() % (LungimeBloc-1));
			        // o cauta daca mai exista in tabela de hassing
			        for(UInt32 i=2;i<j;i++)
				        if(buf_w[i]==buf_w[j])
					        exista = true;
			        //verifica sa nu bata in tabela de hassing	
			        if(buf_w[j]<lungime+3)
				        exista = true;
                }
                while(exista);
	        }

	        //umple restul blocului cu gozuri
	        for(j=lungime+2;j<LungimeBloc;j++)
		        buf_w[j] = (Byte)(fRand.Next()%256);

	        //scrie informatia utila
	        for(UInt32 i=0;i<lungime;i++)
		        buf_w[buf_w[i+2]]= sir[i];

	        try
            {
                //scrie in fisier cat e blocul de lung
                fh1.Write(buf_w, 0, LungimeBloc);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Eroare scriere in fisier: " + ex.Message);
                return false;
            }
            return true;    

        }
        
        public String CalcCheieSerialTr(String idHD,Int16 idMod)
        {
            Byte[] a = new Byte[21];
            if (idHD.Length == 0) 
            {
                MessageBox.Show("Eroare cheie receptionata(sn=0)!");
                return String.Empty;
            }
            UInt16 i = 0;
            for (i = 0; i < idHD.Length; i++)
            {
                a[i] = (Byte)idHD[i];
            }
            //ultimele 2 sunt id-ul modului
            a[18] = (Byte)('0' + idMod / 10);
            a[19] = (Byte)('0' + idMod % 10);
            Byte[] rec = CalcCheieSerial(a, tabhash_transmis);
            if (rec.Length < 20)
            {
                MessageBox.Show("Eroare cheie receptionata(CalcCHeieSerial)!");
                return String.Empty;            
            }
            StringBuilder sBld = new StringBuilder();
            for (UInt16 index = 0; index < 20; index++)
                sBld.Append((Char)rec[index]);
            return sBld.ToString();
        }
        public Byte[] CalcCheieSerial(Byte[] sn,int[] tabhash)
        {
	        Byte[] strCheie = {65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65}
            ,sn1 = {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32};
            Random fRand = new Random((int)DateTime.Now.Ticks);
            for (int ii = 0; ii < DateTime.Now.Millisecond; ii++)
                fRand.Next();
            StringBuilder strKeyB = new StringBuilder();
            UInt16 lgKeye = 0;
            ///determina lungimea seriei hd
            foreach (Byte b in sn)
                if (b != 0)
                {
                    strKeyB.Append((Char)b);
                    lgKeye++;
                }
            String strKey = strKeyB.ToString();
            strKey = strKey.ToUpper();
            UInt16 i=0;
            foreach(Char c1 in strKey) 
	            sn[i++] = (Byte)c1;
	        //umple sirul cu gozuri
            
	        for(i=0;i<20;i++)
		        strCheie[i] = (Byte)('A' + (Byte)(fRand.Next()%25));	

	        //pe prima pozitie pune lungimea chei
            int maxit = min(lgKeye, 19), c;
	        strCheie[0] = (Byte)(65 + maxit);
	        for(i=0;i<maxit;i++)
            {
		        if(eLiteraMare(sn[i]))
                {
			        c = (sn [i] - 65);
			        c= 24  - c;	
			        strCheie[i+1] = (Byte)(c + 65);
		        }
		        if(eCifra(sn[i]))
                {
			        c = (sn [i] - 48);
			        c= 9 - c;
			        strCheie[i+1] = (Byte)(c + 48);
		        }
	        }
	        //le imprastie prin cheie pe toate 20 si lungimea
	        for(i=0;i<20;i++)
		        sn1[tabhash[i]] = strCheie[i];

            return sn1;	
        }

        //citeste informatile din fisierul .din
        
        public bool CitesteDin(String strCale,List<eInfoModule> lstModule)
        {
            ///se construieste lista de module existente
            ///pe calculator
            //LoadModuleID(Directory.GetCurrentDirectory());
            String strPath = null, m_strCheieAuth = null;
	        UInt32 i;

  	        if(strCale.Length == 0)
            {
                strPath = Directory.GetCurrentDirectory() + "\\ERPStudio.din";
	        }
	        else
		        strPath = strCale;

  
            Stream fh1 = null;
            StringBuilder sBuild = new StringBuilder(2000);
            Int32 lgBlocA1, lgBlocCheie;

            FileIOPermission f = new FileIOPermission(FileIOPermissionAccess.AllAccess, strPath);
            try
            {
                f.Demand();
            }
            catch (SecurityException s)
            {
                MessageBox.Show(s.Message, "Message Demand", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                return false;
            }


            if (!File.Exists(strPath))
            {
                ///creaza fisierul
                CreateDin(strPath, lstModule);
                //MessageBox.Show("Modulul de autentificare a fost reinstalat!\nVa rugam sa restartati aplicatia.","ERPStudio",MessageBoxButtons.OK,MessageBoxIcon.Information);
                //return false;
            }
            try
            {
                fh1 = File.Open(strPath, FileMode.Open,FileAccess.ReadWrite,FileShare.ReadWrite);
                Byte[] aiurea = null;
                Int32 lgBloc, lgSN;

                int deplKey = 0;
                Byte[] strDataInceput = CitireBloc(fh1, 6, out lgBloc);
                deplKey += lgBloc;

                DateTime dataInst = new DateTime(
                    strDataInceput[5] * 16 + strDataInceput[4],
                    strDataInceput[1] * 16 + strDataInceput[2],
                    strDataInceput[3] * 16 + strDataInceput[0]);


                //Verificare validitate data de inceput din fisierul din


                aiurea = CitireBloc(fh1, 17, out lgBloc);
                deplKey += lgBloc;
                aiurea = CitireBloc(fh1, 34, out lgBloc);
                deplKey += lgBloc;
                aiurea = CitireBloc(fh1, 4, out lgBloc);
                deplKey += lgBloc;
                lgSN = aiurea[1]*16+aiurea[0];
                aiurea = CitireBloc(fh1, lgSN, out lgBloc);
                deplKey += lgBloc;
                for (i = 0; i < lgSN; i++)
                    sBuild.Append((Char)aiurea[i]);
                String strSerialNo = sBuild.ToString();

                aiurea = CitireBloc(fh1, 24, out lgBloc);
                deplKey += lgBloc;
                aiurea = CitireBloc(fh1, 4, out lgBloc);
                deplKey += lgBloc;

                aiurea = CitireBloc(fh1, 20, out lgBloc);
                deplKey += lgBloc;
                sBuild = new StringBuilder() ;
                for (i = 0; i < 20; i++)
                    sBuild.Append((Char)aiurea[i]);
                String strCheieTransmisa = sBuild.ToString();
                aiurea = CitireBloc(fh1,3, out lgBloc);
                deplKey += lgBloc;
                aiurea = CitireBloc(fh1, 11, out lgBloc);
                deplKey += lgBloc;
                //citire cheie autorizare
                
                sBuild = new StringBuilder();
                aiurea = CitireBloc(fh1,20, out lgBlocCheie);
                if (aiurea[0] != 0)
                {
                    for (i = 0; i < 20; i++)
                        sBuild.Append((Char)aiurea[i]);
                }
                m_strCheieAuth = sBuild.ToString();
                aiurea = CitireBloc(fh1, 17, out lgBloc);
                lgBlocCheie = lgBlocCheie + lgBloc;
                //citire numar de zile de functionare

                aiurea = CitireBloc(fh1, 4, out lgBlocA1);
                deplKey += lgBlocA1;
                m_NumarZileFunctionare =(uint) (aiurea[1]*16 + aiurea[0]);

                aiurea = CitireBloc(fh1, 22, out lgBloc);
                deplKey += lgBloc;
                aiurea = CitireBloc(fh1, 48, out lgBloc);
                deplKey += lgBloc;
                ///de aici incp informatiile despre module
                DeplasamentFisier = fh1.Position; ;
                //numarul de module instalate
                aiurea = CitireBloc(fh1, 4, out lgBloc);
                deplKey += lgBloc;
                int nrModuleInstalate = aiurea[1] * 16 + aiurea[0]; //numarul de module instalate
                long depl_initial = 0;
                eInfoModule eMod=null;
                ushort lgSN2 = 0;
                Byte[] SerialNumber = GetVolumeSerialNumber(out lgSN2);
                for (int idx = 0; idx < nrModuleInstalate; idx++)
                {
                    try
                    {
                        depl_initial = fh1.Position;   
                        CitesteModulDin(fh1, ref deplKey,ref eMod, lstModule);
                        if(eMod!=null)
                            VerificaModule(ref eMod);
                    }
                    catch(Exception)
                    {
                        if (eMod != null)
                        {
                            ///se pozitioneaza la inceputul blocului
                            fh1.Seek(depl_initial, SeekOrigin.Begin);
                            //rescrie blocul daca este corupt
                            SalveazaBlocModul(eMod, SerialNumber, lgSN2, fh1);
                            idx--;
                            // revine la inceputul blocului si-l citeste din nou
                            fh1.Seek(depl_initial, SeekOrigin.Begin);
                        }
                    }
                }
                // se pozitioneaza unde incep informatiile despre module
                fh1.Seek(DeplasamentFisier, SeekOrigin.Begin);
                
                
                ///salveaza numarul de module instalate
                ///

                nrModuleInstalate=0;
                foreach (eInfoModule md in lstModule)
                    if (md.mModule != null)
                        nrModuleInstalate++;

                Byte[] strlgSN = new Byte[4];
                strlgSN[0] = (Byte)(nrModuleInstalate % 16);
                strlgSN[1] = (Byte)(nrModuleInstalate / 16);
                strlgSN[2] = 0;
                strlgSN[3] = 0;
                Boolean done = true;
                done &= SalvareBloc(strlgSN, fh1, 4);
                foreach (eInfoModule ms in lstModule)
                {
                    SalveazaBlocModul(ms, SerialNumber, lgSN2, fh1);
                }
                fh1.Flush();
                fh1.Close();  
            }
            catch (Exception ex)
            {
                if (fh1!= null)
                    fh1.Close();
                throw (new Exception("Eorare deschidere fisier!", ex));
            }

  

           //a fost autorizat
            return true ;
        }

        /// <summary>
        /// cauta in lista de module unul cu un anumit identificator
        /// </summary>
        /// <param name="idModul"></param>
        /// <returns></returns>
        public eInfoModule FindModuleStru(Int16 idModul, List<eInfoModule> lstModule)
        {
            Trace.Assert(lstModule.Count != 0, "Atentie nu s-au incarcat modulele!!!");
            foreach (eInfoModule ms in lstModule)
            {
                if ((ms.idModul!=null) && (Convert.ToInt16(ms.idModul) == idModul))
                    return ms;
            }
            return null;
        }


        public void CitesteModulDin(Stream fh1, ref int deplKey, ref eInfoModule strMod, List<eInfoModule> listaMod)
        {
            Byte[] aiurea = null, strDataInceput=null;
            Int32 lgBloc;
                
            aiurea = CitireBloc(fh1, 24, out lgBloc);
            deplKey += lgBloc;
            aiurea = CitireBloc(fh1,  40, out lgBloc);
            deplKey += lgBloc;

            StringBuilder sBuild = new StringBuilder();
            aiurea = CitireBloc(fh1,  20, out lgBloc);
            deplKey += lgBloc;
            if (aiurea[0] != 0)
            {
                for (int i = 0; i < 20; i++)
                    sBuild.Append((Char)aiurea[i]);
            }
            String Vcheie = sBuild.ToString();

            /// descompune cheia citita si gaseste modulul pentru care e 
            /// generata
            Int16 idModul = 0;
            String hdID = _GetHDIdCl(Vcheie, ref idModul);
            
            strMod = FindModuleStru(idModul, listaMod);
            //seteaza cheia modulului
            if (strMod != null)
                //daca l-a gasit, 
                strMod.CheieModul = Vcheie;


            ///citeste data la care a fost instalat
            ///
            strDataInceput = CitireBloc(fh1,  6, out lgBloc);
            deplKey += lgBloc;

            if (strMod != null)
                strMod.DataInstalare = new DateTime(
                    strDataInceput[5] * 16 + strDataInceput[4],
                    strDataInceput[1] * 16 + strDataInceput[2],
                    strDataInceput[3] * 16 + strDataInceput[0]);

            if (strMod.DataInstalare.Year < 2009)
                strMod.DataInstalare = new DateTime(2009,strMod.DataInstalare.Month,strMod.DataInstalare.Day);
            aiurea = CitireBloc(fh1,  4, out lgBloc);
            deplKey += lgBloc;

            //seteaza starea modulului
            if (strMod != null)
                strMod.StareModul = (Int16)(aiurea[1] * 16 + aiurea[0]);

            aiurea = CitireBloc(fh1, 31, out lgBloc);
            deplKey += lgBloc;
            aiurea = CitireBloc(fh1,  19, out lgBloc);
            deplKey += lgBloc;
            aiurea = CitireBloc(fh1,  27, out lgBloc);
            deplKey += lgBloc;
            aiurea = CitireBloc(fh1,  97, out lgBloc);
            deplKey += lgBloc;

            aiurea = CitireBloc(fh1,  4, out lgBloc);
            deplKey += lgBloc;
            ///seteaza numarul de zile de functionare
            if (strMod != null)
                strMod.NrZileFunctionare = (Int16)(aiurea[1] * 16 + aiurea[0]);
            MyTrace("Modul:" + idModul.ToString() + "-HD:" + hdID + "[DaTA:" + strMod.DataInstalare.ToShortDateString()+
                "Nr.Zile:" + strMod.NrZileFunctionare.ToString() +"Stare:" + strMod.StareModul.ToString());
        
        }
        /// <summary>
        /// verifica modulele daca sun ok!
        /// </summary>
        /// <param name="ms"></param>
        public void VerificaModule(ref eInfoModule ms)
        { 
            ///verifica daca cheia este ok.
            ///citeste seria HD local si o verifica cu cea din cheia modulului
            String localSN = GetVolumeSerialNumber();
            Int16 idModul = 0;
            String fileSN = _GetHDIdCl(ms.CheieModul, ref idModul);
            if (fileSN != localSN )
            { 
                //fisierul a fost generat pe alt sistem si deci modulul 
                //trece in starea demo expirat
                ms.StareModul = 1;
                MyTrace("Pe alta statie" + ms.idModul.ToString());
                return;
            }
            if(ms.CheieModul == String.Empty)
            {
                ms.StareModul = 0;
                MyTrace("Demo" + ms.idModul.ToString());
                return;
                //modul instalat prima data deci e demo
            }

            //daca cheile sunt egale
            if (ms.StareModul == 0)
            {
                int zile = (DateTime.Now - ms.DataInstalare).Days;
                //daca e demo
                if (zile < 0)
                {
                    //a schimbat data calculatorului
                    MyTrace("Reducere zile functionare:" + ms.idModul.ToString());
                    ms.NrZileFunctionare -= (short)zile;
                }
                else
                { 
                    // este la o data ulterioara datei instalarii
                    if (zile > 0)
                    {
                        MyTrace("este la o data ulterioara datei instalarii:" + ms.idModul.ToString());
                        ms.NrZileFunctionare -= 1;
                    }
                    //ms.DataInstalare = DateTime.Now;
                }
                if (ms.NrZileFunctionare <= 0)
                {
                    MyTrace("expirat demo:" + ms.idModul.ToString());
                    ms.StareModul = 1; //expirat dem
                }
            }

        }


        /// <summary>
        /// //returneaza lungimea blocului citit
        /// </summary>
        /// <param name="fh1">handle fisier </param>
        /// <param name="offset">ofsetul de la care citeste</param>
        /// <param name="lungime">lungimea blocului care va fi citit</param>
        /// <param name="deplFis">deplasamentul in fisier</param>
        /// <returns></returns>
        public Byte[] CitireBloc(Stream fh1,Int32 lungime, out Int32 deplFis)
        {
	        Byte[] buf_w = new Byte[1024],ret=new Byte[lungime+1];
	        Boolean done = true;
            deplFis = 0;
            try
            {
                //citeste lungimea blocului

                done = done && (fh1.Read(buf_w, 0, 2) != -1);

                //gaseste lungimea blocului
                deplFis = buf_w[1] * 16 + buf_w[0];

                //citeste restul blocului
                if ((fh1.Position + deplFis -2 > fh1.Length)
                    || (deplFis<=2))
                {
                    MyTrace("Eroare compunere bloc:" + lungime.ToString());
                    throw (new Exception("Bloc eronat"));

                }
                //al doilea parametru e deplasamentul in buffer
                done = done && (fh1.Read(buf_w, 0, deplFis-2) != -1);

                //recompune cheia din bloc
                UInt32 i = 0;
                for (i = 0; i < lungime; i++)
                {
                    ret[i] = 0;
                    if (buf_w[i] > 1)
                        ret[i] = buf_w[buf_w[i] - 2];
                }

                ret[lungime] = 0;
            }
            catch (Exception ex)
            {
                throw (new Exception("Eorare deschidere fisier!", ex));
            }
	        //si returneaza ce a citit
            return ret;
        }
        public String CalcCheieTemp(String cheie)
        {
	        return  _CalcCheieSerialTemp(cheie,tabhash_temp);
        }
        private String _CalcCheieSerialTemp(String sn,int[] tabhash)
        {
	        StringBuilder strCheie= new StringBuilder (),sn1 = new StringBuilder("                ");
            Random fRand = new Random((int)DateTime.Now.Ticks);
            for (int ii = 0; ii < DateTime.Now.Millisecond; ii++)
                fRand.Next();
	        sn = sn.ToUpper();
	        //umple sirul cu gozuri
            UInt16 i = 0;
	        for(i=0;i<16;i++)
		        strCheie.Append('A' + (fRand.Next()%25));	

	        //pe prima pozitie pune lungimea chei
	        int maxit = min(sn.Length,15),c;
	        strCheie[0] = (Char)(65 + maxit);
	        for(i=0;i<maxit;i++)
            {
		        if(eLiteraMare((Byte)sn[i]))
                {
			        c = (sn [i] - 65);
			        c= 24  - c;
                    strCheie[i + 1] = (Char)(c + 65);
		        }
		        if(eCifra((Byte)sn[i]))
                {
			        c = (sn [i] - 48);
			        c= 9 - c;
                    strCheie[i + 1] = (Char)(c + 48);
		        }
	        }
	        //le imprastie prin cheie pe toate 20 si lungimea
	        for(i=0;i<16;i++)
		        sn1[tabhash[i]] = strCheie[i];
	        return sn1.ToString();	
        }
        /// <summary>
        /// returneaza informatiile despre un anumit modul dupa ID-ul in combo
        /// </summary>
        /// <param name="idModul">ideul modulului analizat</param>
        /// <param name="cheie">cheia modulului</param>
        /// <param name="stare">starea modulului</param>
        /// <param name="zileFunc">nr. de zile de functionare ramase</param>
        public void getModuleInfo(Int16 idModul, ref String cheie, ref Int16 stare, ref Int16 zileFunc,ref DateTime dt,List<eInfoModule> lstModule)
        {
            cheie = String.Empty;
            stare = 0; //demo
            zileFunc = 0; //expirat
            foreach (eInfoModule ms in lstModule)
            {
                if (ms.IDLista == idModul)
                {
                    cheie = ms.CheieModul;
                    stare = ms.StareModul;
                    zileFunc = ms.NrZileFunctionare;
                    dt = ms.DataInstalare;
                    return;
                }
            }
        }
        /// <summary>
        /// returneaza informatiile despre un anumit modul dupa ID-ul modulului
        /// </summary>
        /// <param name="idModul">ideul modulului analizat</param>
        /// <param name="cheie">cheia modulului</param>
        /// <param name="stare">starea modulului</param>
        /// <param name="zileFunc">nr. de zile de functionare ramase</param>
        public void getModuleInfo2(Int16 idModul, ref String cheie, ref Int16 stare, ref Int16 zileFunc,List<eInfoModule> lstModule)
        {
            cheie = String.Empty;
            stare = 0; //demo
            zileFunc = 0; //expirat
            foreach (eInfoModule ms in lstModule)
            {
                if (Convert.ToInt16(ms) == idModul)
                {
                    cheie = ms.CheieModul;
                    stare = ms.StareModul;
                    zileFunc = ms.NrZileFunctionare;
                }
            }
        }
    }
}
